/*
 *  Copyright (c) 2011 Leibniz Institute of Plant Genetics and Crop Plant Research (IPK), Gatersleben, Germany.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the GNU Lesser Public License v2.1
 *  which accompanies this distribution, and is available at
 *  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 *
 *  Contributors:
 *      Leibniz Institute of Plant Genetics and Crop Plant Research (IPK), Gatersleben, Germany - RMI Client, FileChooser and WebDAV
 */
package de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.primary_data;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import io.milton.http.Auth;
import io.milton.resource.PropFindableResource;
import io.milton.http.Request;
import io.milton.http.Request.Method;

import de.ipk_gatersleben.bit.bi.edal.primary_data.file.PrimaryDataDirectoryException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.file.EdalException;
import de.ipk_gatersleben.bit.bi.edal.primary_data.security.EdalAuthenticateException;
import de.ipk_gatersleben.bit.bi.edal.publication.IpkAuthenticationProcess;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.ClientDataManager;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.ClientPrimaryDataDirectory;
import de.ipk_gatersleben.bit.bi.edal.rmi.client.ClientPrimaryDataEntity;
import de.ipk_gatersleben.bit.bi.edal.rmi.server.Authentication;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.FileSystemCache;
import de.ipk_gatersleben.bit.bi.edal.webdav.wrapper.FileSystemHandler;

/**
 * A resource representing a PrimaryDataEntity.
 * 
 * @author benz
 */

public class PrimaryDataEntityResource implements PropFindableResource {
	// the primary data entity represented by this resource
	protected ClientPrimaryDataEntity entity;
	// an instance of FileSystemHandler to handle requests to EDAL
	protected FileSystemHandler fileSystemHandler;
	protected String path;
	protected String username = "";

	public PrimaryDataEntityResource(String path,
			FileSystemHandler fileSystemHandler) throws RemoteException,
			PrimaryDataDirectoryException {
		this.path = path;
		if (fileSystemHandler != null) {
			this.fileSystemHandler = fileSystemHandler;
			this.entity = fileSystemHandler.getEntity(path);
		}
	}

	/**
	 * Check if the resource represents an existing
	 * {@link ClientPrimaryDataEntity}
	 * 
	 * @see FileSystemHandler#getEntity(String)
	 * @return true if the resource represents an existing
	 *         {@link ClientPrimaryDataEntity}
	 */
	public boolean exists() {
		return entity != null;
	}

	/**
	 * Check if the {@link ClientPrimaryDataEntity} represented by this
	 * {@link PrimaryDataEntityResource} is a directory.
	 * 
	 * @return true, if the {@link PrimaryDataEntityResource} is a directory.
	 */
	public boolean isDirectory() {
		try {
			return entity.isDirectory();
		} catch (RemoteException e) {
			ClientDataManager.logger.error(e.toString());
		}
		return false;
	}

	/**
	 * Returns an instance of ClientPrimaryDataEntity represented by this
	 * Resource
	 * 
	 * @return an instance of ClientPrimaryDataEntity represented by this
	 *         Resource
	 */
	public ClientPrimaryDataEntity getEntity() {
		return this.entity;
	}

	@Override
	public Object authenticate(String user, String password) {
		Map info = new HashMap();
		info.put("user", user);
		info.put("password", password);
		return info;
	}

	@Override
	public boolean authorise(Request request, Method method, Auth auth) {
		if (auth == null || auth.getTag() == null) {
			return false;
		}

		Map info = (Map) (auth.getTag());
		username = info.get("user").toString();
		if (FileSystemCache.get(username) != null) {
			return true;
		} else {
			//Authentication loginobj = new Authentication(username, info.get("password").toString());
			Authentication authentication = new Authentication(new IpkAuthenticationProcess().getSubject());
			try {
				/*
				ClientDataManager myClient = new ClientDataManager(
						FileSystemHandler.REGISTRY_PORT,
						FileSystemHandler.HOST, loginobj);
						*/
				ClientDataManager myClient = new ClientDataManager(FileSystemHandler.REGISTRY_PORT, FileSystemHandler.HOST, authentication);
				ClientPrimaryDataDirectory rootDirectory = myClient
						.getRootDirectory();
				fileSystemHandler = new FileSystemHandler(rootDirectory);
				FileSystemCache.put(username, fileSystemHandler);
				entity = fileSystemHandler.getEntity(path);
				return true;
			} catch (RemoteException e) {
				ClientDataManager.logger
						.fatal("Failed to load/initialize FileSystemHandler: "
								+ e.getMessage());
			} catch (NotBoundException e) {
				ClientDataManager.logger
						.fatal("Failed to load/initialize FileSystemHandler: "
								+ e.getMessage());
			} catch (PrimaryDataDirectoryException e) {
				ClientDataManager.logger
						.fatal("Failed to load/initialize FileSystemHandler: "
								+ e.getMessage());
			} catch (EdalAuthenticateException e) {
				ClientDataManager.logger
						.fatal("Failed to load/initialize FileSystemHandler: "
								+ e.getMessage());
			} catch (EdalException e) {
				ClientDataManager.logger
						.fatal("Failed to load/initialize FileSystemHandler: "
								+ e.getMessage());
			}

		}

		return false;
	}

	@Override
	public String checkRedirect(Request request) {
		return null;
	}

	@Override
	public Date getModifiedDate() {
		try {
			return this.getEntity().getCurrentVersion().getRevisionDate()
					.getTime();
		} catch (Exception e) {
			ClientDataManager.logger.error("Failed to get modified date :"
					+ e.toString());
		}
		return null;
	}

	@Override
	public String getName() {
		if (this.getEntity() != null) {
			try {
				return this.getEntity().getName();
			} catch (RemoteException e) {
				ClientDataManager.logger.error("Failed to get name: "
						+ e.toString());
			}
		}
		return null;
	}

	@Override
	public String getRealm() {
		if (this.getEntity() != null) {
			try {
				return this.getEntity().getID();
			} catch (RemoteException e) {
				ClientDataManager.logger.error("Failed to get ID: "
						+ e.toString());
			}
		}
		return null;
	}

	@Override
	public String getUniqueId() {
		if (this.getEntity() != null) {
			try {
				return this.getEntity().getID();
			} catch (RemoteException e) {
				ClientDataManager.logger.error("Failed to get ID: "
						+ e.toString());
			}
		}
		return null;
	}

	@Override
	public Date getCreateDate() {
		try {
			return this.getEntity().getCurrentVersion().getCreationDate()
					.getTime();
		} catch (Exception e) {
			ClientDataManager.logger.error("Failed to get create date: "
					+ e.toString());
		}
		return null;
	}
}
